package com.qms.qep.service.impl;

import com.qms.qep.service.ISpcAnalysisService;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * SPC分析服务实现类
 */
@Service
public class SpcAnalysisServiceImpl implements ISpcAnalysisService {

    /**
     * 获取过程能力分析数据
     *
     * @param productId 产品ID
     * @param processId 工序ID
     * @param paramId 参数ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 过程能力分析数据
     */
    @Override
    public Map<String, Object> getCapabilityAnalysis(String productId, String processId, String paramId,
                                                     String startDate, String endDate) {
        // 创建返回结果
        Map<String, Object> result = new HashMap<>();

        // 添加示例数据
        result.put("lsl", 9.0);  // 规格下限
        result.put("usl", 11.0); // 规格上限
        result.put("target", 10.0); // 目标值
        result.put("mean", 10.2); // 平均值
        result.put("standardDeviation", 0.3); // 标准差

        // 过程能力指数
        result.put("cp", 1.33);
        result.put("cpk", 1.22);
        result.put("pp", 1.28);
        result.put("ppk", 1.18);

        // 添加样本数据用于绘制直方图
        List<Double> samples = generateSamples(10.2, 0.3, 100);
        result.put("samples", samples);

        // 数据分布情况
        Map<String, Object> distribution = new HashMap<>();
        distribution.put("withinSpecs", 97.5); // 在规格范围内的百分比
        distribution.put("aboveUsl", 1.2); // 高于上限的百分比
        distribution.put("belowLsl", 1.3); // 低于下限的百分比
        result.put("distribution", distribution);

        // 建议与结论
        result.put("conclusion", "过程能力满足要求，建议继续监控");

        return result;
    }

    /**
     * 获取控制图数据
     *
     * @param productId 产品ID
     * @param processId 工序ID
     * @param paramId 参数ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param chartType 控制图类型（xbar-r, p, c等）
     * @return 控制图数据
     */
    @Override
    public Map<String, Object> getControlChart(String productId, String processId, String paramId,
                                               String startDate, String endDate, String chartType) {
        // 创建返回结果
        Map<String, Object> result = new HashMap<>();

        // 样本数量
        result.put("sampleSize", 30);

        // 中心线值
        result.put("centerLine", 10.0);

        // 控制限
        result.put("ucl", 10.5);
        result.put("lcl", 9.5);

        // 异常点数量
        result.put("abnormalCount", 2);

        // 过程能力指数
        result.put("cpk", 1.22);

        // 控制状态
        result.put("controlStatus", "基本受控");

        // 构建主图数据（X图或单值图）
        List<Map<String, Object>> mainData = new ArrayList<>();
        List<String> categories = new ArrayList<>();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();

        // 生成模拟数据
        for (int i = 0; i < 30; i++) {
            Map<String, Object> point = new HashMap<>();
            cal.add(Calendar.DAY_OF_MONTH, -1);

            double value = 10.0 + Math.random() * 0.8 - 0.4;
            // 制造两个异常点
            if (i == 5) value = 10.7; // 超上限
            if (i == 15) value = 9.3; // 超下限

            point.put("sample", i + 1);
            point.put("value", Math.round(value * 100) / 100.0);
            point.put("date", sdf.format(cal.getTime()));

            mainData.add(point);
            categories.add("样本" + (i + 1));
        }

        // 倒序排列，使最新数据在右侧
        Collections.reverse(mainData);
        Collections.reverse(categories);

        result.put("mainData", mainData);
        result.put("categories", categories);

        // 构建次图数据（R图或MR图）
        List<Map<String, Object>> subData = new ArrayList<>();
        if (chartType.equals("xbar-r") || chartType.equals("i-mr")) {
            double rUcl = 1.5;
            double rLcl = 0;
            double rCl = 0.7;

            for (int i = 0; i < mainData.size(); i++) {
                Map<String, Object> point = new HashMap<>();
                double range = 0.2 + Math.random() * 0.6;

                point.put("sample", i + 1);
                point.put("value", Math.round(range * 100) / 100.0);
                point.put("date", mainData.get(i).get("date"));

                subData.add(point);
            }

            result.put("subData", subData);
            result.put("rUcl", rUcl);
            result.put("rLcl", rLcl);
            result.put("rCl", rCl);
        }

        // 违规规则
        List<Integer> westernViolations = Arrays.asList(1, 3);
        List<Integer> nelsonViolations = Arrays.asList(2);
        result.put("westernViolations", westernViolations);
        result.put("nelsonViolations", nelsonViolations);

        // 异常点详情
        List<Map<String, Object>> abnormalPoints = new ArrayList<>();

        Map<String, Object> point1 = new HashMap<>();
        point1.put("number", 6);
        point1.put("time", mainData.get(5).get("date"));
        point1.put("value", mainData.get(5).get("value"));
        point1.put("rules", Arrays.asList("W1"));

        Map<String, Object> point2 = new HashMap<>();
        point2.put("number", 16);
        point2.put("time", mainData.get(15).get("date"));
        point2.put("value", mainData.get(15).get("value"));
        point2.put("rules", Arrays.asList("W1", "N2"));

        abnormalPoints.add(point1);
        abnormalPoints.add(point2);

        result.put("abnormalPoints", abnormalPoints);

        return result;
    }

    /**
     * 获取趋势分析数据
     *
     * @param productId 产品ID
     * @param processId 工序ID
     * @param paramId 参数ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param predictNext 是否预测下一阶段
     * @return 趋势分析数据
     */
    @Override
    public Map<String, Object> getTrendAnalysis(String productId, String processId, String paramId,
                                                String startDate, String endDate, Boolean predictNext) {
        // 创建返回结果
        Map<String, Object> result = new HashMap<>();

        // 当前统计数据
        result.put("currentMean", 10.2);
        result.put("standardDeviation", 0.3);
        result.put("trendType", "上升");
        result.put("predictionReliability", "85%");

        // 构建趋势数据点
        List<Map<String, Object>> points = new ArrayList<>();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();

        // 生成模拟数据，呈上升趋势
        for (int i = 0; i < 20; i++) {
            Map<String, Object> point = new HashMap<>();
            cal.add(Calendar.DAY_OF_MONTH, -1);

            // 上升趋势基础值
            double baseValue = 10.0 + (i * 0.03);
            // 添加随机波动
            double value = baseValue + Math.random() * 0.3 - 0.15;

            point.put("sampleTime", sdf.format(cal.getTime()));
            point.put("value", Math.round(value * 100) / 100.0);
            point.put("movingAverage", Math.round((baseValue) * 100) / 100.0);
            point.put("lowerBound", Math.round((baseValue - 0.5) * 100) / 100.0);
            point.put("upperBound", Math.round((baseValue + 0.5) * 100) / 100.0);

            // 状态判断
            String status = "正常";
            if (value > baseValue + 0.4) status = "偏高";
            if (value < baseValue - 0.4) status = "偏低";

            point.put("status", status);
            point.put("note", "");

            points.add(point);
        }

        // 倒序排列，使最新数据在列表顶部
        Collections.reverse(points);
        result.put("points", points);

        // 趋势线数据
        List<Double> trendData = new ArrayList<>();
        List<String> timeLabels = new ArrayList<>();

        for (int i = points.size() - 1; i >= 0; i--) {
            Map<String, Object> point = points.get(i);
            trendData.add((Double)point.get("value"));
            timeLabels.add((String)point.get("sampleTime"));
        }

        result.put("trendData", trendData);
        result.put("timeLabels", timeLabels);

        // 如果需要预测
        if (predictNext) {
            Map<String, Object> prediction = new HashMap<>();
            prediction.put("mean", 10.6);
            prediction.put("lowerBound", 10.3);
            prediction.put("upperBound", 10.9);
            prediction.put("reliability", "85%");
            prediction.put("modelType", "线性回归");
            prediction.put("upperRisk", 20);
            prediction.put("lowerRisk", 5);
            prediction.put("riskLevel", "中");
            prediction.put("suggestion", "建议密切关注，可能需要调整工艺参数");

            result.put("prediction", prediction);
        }

        return result;
    }

    /**
     * 获取相关性分析数据
     *
     * @param paramId1 参数1ID
     * @param paramId2 参数2ID
     * @param productId 产品ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 相关性分析数据
     */
    @Override
    public Map<String, Object> getCorrelationAnalysis(String paramId1, String paramId2, String productId,
                                                      String startDate, String endDate) {
        // 创建返回结果
        Map<String, Object> result = new HashMap<>();

        // 参数信息
        Map<String, Object> param1 = new HashMap<>();
        param1.put("id", paramId1);
        param1.put("name", "参数1");
        param1.put("unit", "mm");

        Map<String, Object> param2 = new HashMap<>();
        param2.put("id", paramId2);
        param2.put("name", "参数2");
        param2.put("unit", "°C");

        result.put("param1", param1);
        result.put("param2", param2);

        // 相关性分析结果
        result.put("correlationCoefficient", 0.85);
        result.put("correlationStrength", "强");
        result.put("regressionEquation", "y = 1.2x + 3.5");
        result.put("determinationCoefficient", 0.72); // R²值

        // 生成散点图数据
        List<List<Double>> scatterData = new ArrayList<>();

        // 基于线性关系生成数据点：y = 1.2x + 3.5 并添加随机误差
        for (int i = 0; i < 50; i++) {
            List<Double> point = new ArrayList<>();
            double x = 8 + Math.random() * 4; // x 在 8-12 之间
            double y = 1.2 * x + 3.5 + (Math.random() - 0.5) * 2; // 添加随机误差

            point.add(Math.round(x * 10) / 10.0);
            point.add(Math.round(y * 10) / 10.0);

            scatterData.add(point);
        }

        result.put("scatterData", scatterData);

        // 回归线上的点
        List<List<Double>> regressionLine = new ArrayList<>();
        double minX = 8;
        double maxX = 12;

        List<Double> point1 = new ArrayList<>();
        point1.add(minX);
        point1.add(1.2 * minX + 3.5);

        List<Double> point2 = new ArrayList<>();
        point2.add(maxX);
        point2.add(1.2 * maxX + 3.5);

        regressionLine.add(point1);
        regressionLine.add(point2);

        result.put("regressionLine", regressionLine);

        // 结论与建议
        result.put("conclusion", "两参数之间存在显著正相关关系，建议在工艺调整时综合考虑");

        return result;
    }

    /**
     * 生成符合正态分布的随机样本
     */
    private List<Double> generateSamples(double mean, double stdDev, int count) {
        List<Double> samples = new ArrayList<>();
        Random random = new Random();

        for (int i = 0; i < count; i++) {
            double value = mean + random.nextGaussian() * stdDev;
            samples.add(Math.round(value * 100) / 100.0);
        }

        return samples;
    }
}